﻿using System;
using System.Collections.Generic;
using DC2010.Logic;
using DC2010.Objects.Structures;
using DC2010.Systems;
using DC2010.Manager;
using log4net.Config;
using log4net;
using System.Reflection;
using System.Threading;
using System.IO;

namespace DC2010
{
    public class Root
    {
        public static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        private static Root _i;
        private Root()
        { 
        }

        public void Ini()
        {
			try			
			{
				DateTime dtStart = DateTime.Now;

				//_i.GameDirectory = "Dungeons\\DeepCave\\";

				_i.GlobalTimer = new System.Timers.Timer();
				_i.GlobalTimer.Interval = 1000;
				_i.GlobalTimer.Start();

				Rnd = new Random();
				C = new Calculations();

				// This system handles multiple language support.
				_i.ResourceManager = new ResourceManager();

				// Everything what is possible to do with items is defined here. SWING, THROW, etc...
				// Any Action can call how many effects it wants...so double swings possible.
				_i.ActionSystem = new ActionSystem();
				
				// Eatch tile has its own representation. Those representations are stored using this system.
				_i.TileSystem = new TileSystem();
				
				// Gateway for environment changes. Any action in action system calls corresponding effect. Effect can be understood as
				// atomic operations that could change something. Depending on effect implementation.
				_i.EffectSystem = new EffectSystem();
				
				// Doors can be understood as special form of tile. Possibly this system will be in future removed and replace with DoorTile.cs
				// TODO: Remove this system
				_i.DoorSystem = new DoorSystem();
				
				// Each RPG game has its items. Thru this system, all items are handled.
				_i.ItemSystem = new ItemSystem();
				
				// Each RPG game has its items. Thru this system, all items are handled.
				_i.CreatureSystem = new CreatureSystem();

				// Floor can be edited independently on any map there are used in. Each floor can be understood as on level in dungeon
				_i.FloorSystem = new FloorSystem();

				// This system joins multiple floors into one map, which lately will define on game. For example DM = Map and it will contain 14 floors.
				_i.MapSystem = new MapSystem();
				
				// System handles item sets and effects which will be applied when worn such sets.
				_i.SetSystem = new SetSystem();
				
				// Probably obsolette because im using old DM skill system.
				_i.SkillSystem = new SkillSystem();
				
				// All runes are defined in this system.
				_i.RuneSystem = new RuneSystem();

				// All possible spells are defined here. We are referencing to runes here - when creating spells.
				_i.SpellSystem = new SpellSystem();
				
				// Not system with Data, Gfx and Info but this simply handles moving calculations in game. 
				// It should be removed from here and replaced with normal class.
				// TODO: Remove this system and replace with logic class.
				_i.MovementSystem = new MovementSystem();
				
				// This is very similar to effect system. But with one diference. 
				// Here is logic which desides which branch of effects will be called.
				_i.ConditionSystem = new ConditionSystem();
				
				// Dialogs, communication with player, etc. NPCs dialogs definition
				_i.DialogSystem = new DialogSystem();
				
				// Each creature if in dungeon is encapsulated into a party.
				// This deletes difference between player and creatures.
				// If we can take this to extreme we can play in monster party :)
				_i.PartySystem = new PartySystem();
				
				// Gfx definitions. How many frames and how fast we should draw animations etc...Every Gfx from systems will look here.
				_i.SpriteSystem = new SpriteSystem();
				
				// Way to react events....not sure about this.
				_i.EventSystem = new EventSystem();

				_i.AISystem = new AISystem();

				_i.SoundQueue = new QueueEx<string>();

				_i.AISystem.Init(_i.GameDirectory+"AI"); _i.LoadingStatus = "Monsters starts to see the light...".ToUpper();
				_i.ActionSystem.Init(_i.GameDirectory+"Action"); _i.LoadingStatus = "Preparing actions...".ToUpper();
				_i.SpriteSystem.Init(_i.GameDirectory+"Sprite"); _i.LoadingStatus = "Starting animations...".ToUpper();
				_i.TileSystem.Init(_i.GameDirectory+"Tiles");                   _i.LoadingStatus = "Book of tiles opened...".ToUpper();
				_i.EffectSystem.Init(_i.GameDirectory+"Effects");                 _i.LoadingStatus = "Effects released...".ToUpper();
				_i.EventSystem.Init(_i.GameDirectory+"Events"); _i.LoadingStatus = "Events released...".ToUpper();
				_i.ResourceManager.Init(_i.GameDirectory+"EN");          _i.LoadingStatus = "Resource manager initialized...".ToUpper();
				_i.DoorSystem.Init(_i.GameDirectory+"Doors");                   _i.LoadingStatus = "Doors opened...".ToUpper();
				_i.ConditionSystem.Init(_i.GameDirectory+"Conditions");              _i.LoadingStatus = "Conditions initialized...".ToUpper();
				_i.ItemSystem.Init(_i.GameDirectory+"Items");                   _i.LoadingStatus = "Creating items...".ToUpper();
				_i.CreatureSystem.Init(_i.GameDirectory+"Creatures");               _i.LoadingStatus = "Creating life...".ToUpper();
				_i.RuneSystem.Init(_i.GameDirectory+"Runes");                   _i.LoadingStatus = "Rune system encrypted...".ToUpper();
				_i.SpellSystem.Init(_i.GameDirectory+"Spells");                  _i.LoadingStatus = "Spells charged...".ToUpper();
				_i.SkillSystem.Init(_i.GameDirectory+"Skills");                  _i.LoadingStatus = "Skills initialized...".ToUpper();
				_i.MapSystem.Init(_i.GameDirectory+"Maps");                    _i.LoadingStatus = "Maps loaded...".ToUpper();
				_i.SetSystem.Init();                    _i.LoadingStatus = "Sets initialized...".ToUpper();
				_i.MovementSystem.Init();               _i.LoadingStatus = "Life can move now...".ToUpper();
				_i.PartySystem.Init(_i.GameDirectory+"Parties");                  _i.LoadingStatus = "Life is interacting now...".ToUpper();
				_i.DialogSystem.Init(_i.GameDirectory+"Dialogs");                 _i.LoadingStatus = "You can speak...".ToUpper();
				_i.FloorSystem.Init(_i.GameDirectory+"Floors");                  _i.LoadingStatus = "Cleaning floors...".ToUpper();

				//this one must be LAST!!!!
				_i.GameSystem = new GameSystem();       _i.LoadingStatus = "Loading textures...".ToUpper();
				_i.GameSystem.Init();

				log.Debug("Complete game init took: " + (DateTime.Now - dtStart).TotalSeconds + " seconds");

				_i.Log = "";

				_i.LoadingStatus = "Loaded";
			}
			catch(Exception ex)
			{
				log.Error("Error: "+ex.Message);
			}
        }
		
		public void ChangeGame(string sNewGame)
		{
			_i.GameDirectory = "Dungeons\\"+sNewGame+"\\";
			Init();
		
		}

        public void Init()
        {
            ThreadStart pts = Ini;
            Thread t = new Thread(pts);
            t.Start();
        }

        public static Root I
        {
            get
            {
                if (_i == null)
                {
                    //configure log4net
                    XmlConfigurator.Configure();

                    _i = new Root();
                    _i.LoadingStatus = "Loading started...";
                }
                return _i;
            }
        }


        public AISystem AISystem { get; set; }
        public ActionSystem ActionSystem { get; set; }
        public PartySystem PartySystem { get; set; }
        public CreatureSystem CreatureSystem { get; set; }
        public ItemSystem ItemSystem { get; set; }
        public MapSystem MapSystem { get; set; }
        public SetSystem SetSystem { get; set; }
        public SkillSystem SkillSystem { get; set; }
        public GameSystem GameSystem { get; set; }
        public MovementSystem MovementSystem { get; set; }
        public EffectSystem EffectSystem { get; set; }
        public DialogSystem DialogSystem { get; set; }
        public ConditionSystem ConditionSystem { get; set; }
        public SpellSystem SpellSystem { get; set; }
        public RuneSystem RuneSystem { get; set; }
        public DoorSystem DoorSystem { get; set; }
        public TileSystem TileSystem { get; set; }
        public FloorSystem FloorSystem { get; set; }
        public SpriteSystem SpriteSystem { get; set; }
        public EventSystem EventSystem { get; set; }

        public Calculations C { get; set; }



        public string Log { get; set; }
        public string GameDirectory { get; set; }

        public ResourceManager ResourceManager { get; set; }

        public QueueEx<string> SoundQueue { get; set; }

        public List<string> CreatedTimers_objectIds { get; set; }
        public string LoadingStatus { get; set; }

        public Random Rnd { get; set; }


        /// <summary>
        /// Profile id, which is used to load game
        /// </summary>
        public string Profile { get; set; }


        public void Run()
        {
 
        }

        public void RunDemo()
        {
            _i.GameSystem.Run();
        }

        public System.Timers.Timer GlobalTimer { get; set; }

        public static string GetCode(int A, int B)
        {
            string result = "";
            if (A < 0) result += "m";
            result += Math.Abs(A).ToString() + "_";

            if (B < 0) result += "m";
            result += Math.Abs(B).ToString();

            return result;
        }

    }
}
